import wx
import wx.grid
import pandas as pd
import os
import message_log


class HomeFrame(wx.Frame):
    def __init__(self, identity):
        wx.Frame.__init__(self, None, -1, u'主界面', size=(1000, 670),
                          style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)
        icon = wx.Icon(name='苦短.jpg', type=wx.BITMAP_TYPE_JPEG)  # 设置图标
        self.SetIcon(icon)
        self.Center()
        self.SetBackgroundColour('white')
        self.identity = identity
        font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
        self.SetFont(font)
        self.panel = wx.Panel(self)
        self.log = message_log.Log()
        if identity in ['教师', '管理员']:
            self._plan()
        else:  # 此分支为学生
            self.student()

    def _plan(self, row=25):  # 布局函数(默认生成1行表格)
        vbox = wx.BoxSizer(wx.VERTICAL)  # 创建竖直方向box布局管理器
        # 创建logo静态文本，设置字体属性-->竖直方向第一层
        logo = wx.StaticText(self.panel, label="学生信息管理系统")
        font = logo.GetFont()  # 获取界面字体大小
        font.PointSize += 20  # 在界面字体大小基础上加20
        font = font.Bold()  # 加粗
        logo.SetFont(font)
        # 添加logo静态文本到vbox布局管理器
        vbox.Add(logo, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        # ---------------第一层完毕-----------------
        # 创建左侧静态框
        left_box = wx.StaticBox(self.panel, label="选择操作")
        # 创建竖直方向box布局管理器
        left_vbox = wx.StaticBoxSizer(left_box, wx.VERTICAL)
        # 创建操作按钮、绑定事件处理，绑定id
        watch_button = wx.Button(self.panel, id=10, label="查看学生信息", size=(150, 50))
        add_button = wx.Button(self.panel, id=11, label="添加学生信息", size=(150, 50))
        delete_button = wx.Button(self.panel, id=12, label="删除学生信息", size=(150, 50))
        quit_button = wx.Button(self.panel, id=13, label="退出系统", size=(150, 50))
        # self.Bind(wx.EVT_BUTTON, self.ClickButton, id=10, id2=13)
        # 添加操作按钮到左侧竖直布局管理器
        left_vbox.Add(watch_button, 0, wx.EXPAND | wx.BOTTOM, 40)
        left_vbox.Add(add_button, 0, wx.EXPAND | wx.BOTTOM, 40)
        left_vbox.Add(delete_button, 0, wx.EXPAND | wx.BOTTOM, 40)
        left_vbox.Add(quit_button, 0, wx.EXPAND | wx.BOTTOM, 200)
        # ---------------第二层左侧框布局完毕--------------
        # 创建右侧静态框
        self.right_box = wx.StaticBox(self.panel, label="显示/操作窗口", size=(800, 500))
        # 创建垂直方向box布局管理器
        self.right_vbox = wx.StaticBoxSizer(self.right_box, wx.VERTICAL)
        # 创建right_box内水平方向box布局管理器
        # self.right_hbox = wx.BoxSizer()  # 在增、删、改方法中用于添加一个按钮位置
        # 添加表格
        col_labels = ['学号', '姓名', '性别', '年级', '学院', '专业', '课程']
        col_widths = [120, 80, 40, 60, 100, 100, 100]
        self.create_grid(row, col_labels, col_widths)  # 参数是行数
        # self.right_hbox.Add(self.grid, 0, wx.EXPAND | wx.BOTTOM, 5)
        self.right_vbox.Add(self.grid, 0, wx.EXPAND | wx.BOTTOM, 5)
        # 创建水平方向box布局管理器
        hbox = wx.BoxSizer()
        hbox.Add(left_vbox, 0, wx.EXPAND | wx.BOTTOM, 5)
        hbox.Add(self.right_vbox, 0, wx.EXPAND | wx.BOTTOM, 5)
        # # 将hbox添加到垂直box
        vbox.Add(hbox, proportion=0, flag=wx.CENTER)
        self.panel.SetSizer(vbox)

        self.Bind(wx.EVT_BUTTON, self.click_button)

    def student(self):
        vbox = wx.BoxSizer(wx.VERTICAL)  # 创建竖直方向box布局管理器
        # 创建logo静态文本，设置字体属性-->竖直方向第一层
        logo = wx.StaticText(self.panel, label="学生信息管理系统")
        font = logo.GetFont()  # 获取界面字体大小
        font.PointSize += 20  # 在界面字体大小基础上加20
        font = font.Bold()  # 加粗
        logo.SetFont(font)
        # 添加logo静态文本到vbox布局管理器
        vbox.Add(logo, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        # ---------------第一层完毕-----------------
        # 学生个人信息-->竖直方向第二层
        left_box = wx.StaticBox(self.panel, label="个人信息")
        left_vbox = wx.StaticBoxSizer(left_box, wx.VERTICAL)
        # text = f'姓名：{2}\t学号：{3}\t性别：{4}\t年级：{5}\t专业：{6}\t班级：{1}'
        name = wx.StaticText(self.panel, label=f'姓名：{1}')
        left_vbox.Add(name, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        stu_id = wx.StaticText(self.panel, label=f'学号：{2}')
        left_vbox.Add(stu_id, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        sex = wx.StaticText(self.panel, label=f'性别：{3}')
        left_vbox.Add(sex, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        grade = wx.StaticText(self.panel, label=f'年级：{4}')
        left_vbox.Add(grade, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        zy = wx.StaticText(self.panel, label=f'专业：{5}')
        left_vbox.Add(zy, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        cls = wx.StaticText(self.panel, label=f'班级：{6}')
        left_vbox.Add(cls, proportion=0, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)

        # 创建中间静态框
        mid_box = wx.StaticBox(self.panel, label="选择操作")
        # 创建竖直方向box布局管理器
        mid_vbox = wx.StaticBoxSizer(mid_box, wx.VERTICAL)
        # 创建操作按钮、绑定事件处理，绑定id
        watch_button = wx.Button(self.panel, id=10, label="查看成绩", size=(150, 50))
        quit_button = wx.Button(self.panel, id=13, label="退出系统", size=(150, 50))
        # self.Bind(wx.EVT_BUTTON, self.ClickButton, id=10, id2=13)
        # 添加操作按钮到左侧竖直布局管理器
        mid_vbox.Add(watch_button, 0, wx.EXPAND | wx.BOTTOM, 40)
        mid_vbox.Add(quit_button, 0, wx.EXPAND | wx.BOTTOM, 200)
        # ---------------第二层左侧框布局完毕--------------
        # 创建右侧静态框
        self.right_box = wx.StaticBox(self.panel, label="显示窗口", size=(800, 500))
        # 创建垂直方向box布局管理器
        self.right_vbox = wx.StaticBoxSizer(self.right_box, wx.VERTICAL)
        # 创建right_box内水平方向box布局管理器
        # 添加表格
        col_labels = ['语文', '数学', '英语', '物理', '化学', '生物', '政治', '历史', '地理', '技术']
        col_widths = [50, 50, 50, 50, 50, 50, 50, 50, 50, 50]
        self.create_grid(1, col_labels, col_widths)  # 参数是行数
        self.right_vbox.Add(self.grid, 0, wx.EXPAND | wx.BOTTOM, 5)
        # 创建水平方向box布局管理器
        hbox = wx.BoxSizer()
        hbox.Add(left_vbox, 0, wx.EXPAND | wx.BOTTOM, 5)
        hbox.Add(mid_vbox, 0, wx.EXPAND | wx.BOTTOM, 5)
        hbox.Add(self.right_vbox, 0, wx.EXPAND | wx.BOTTOM, 5)
        # # 将hbox添加到垂直box
        vbox.Add(hbox, proportion=0, flag=wx.CENTER)
        self.panel.SetSizer(vbox)

        self.Bind(wx.EVT_BUTTON, self.click_button)

    def create_grid(self, row, col_labels, col_widths):
        self.grid = wx.grid.Grid(self.panel, -1)
        self.grid.CreateGrid(row, len(col_labels))
        k = 0
        for i, j in zip(col_labels, col_widths):
            self.grid.SetColLabelValue(k, i)
            self.grid.SetColSize(k, j)
            for r in range(row):
                self.grid.SetReadOnly(r, k)
            k += 1

    def click_button(self, event):
        event_id = event.GetId()
        if event_id == 10:
            print("查询操作！")
            df = ExcelData().df
            sf = SearchFrame(self)   # 创建查询窗口实例
            sf.Show()
            sf.Bind(wx.EVT_BUTTON, lambda evt, para1=df, para2=sf: self.match(evt, para1, para2), sf.btn1)

        elif event_id == 11:
            print('增加操作！')
            af = AddFrame(self)
            af.Show()

        elif event_id == 12:
            print('删除操作！')
            df = ExcelData().df
            df.fillna('', inplace=True)
            row = len(df.index)
            if row > 25:
                self.grid.AppendRows(row - 25)
            for i in range(row):
                for k, info in enumerate(list(df.iloc[i])):
                    self.grid.SetCellValue(i, k, info)
            del_frame = DeleteFrame(self)
            del_frame.Show()
            # 设置lambda函数用于给事件函数传递参数df
            self.Bind(wx.EVT_BUTTON,
                      lambda evt, para1=df, para2=del_frame:
                      self.delete(evt, para1, para2), del_frame.btn1)

        elif event_id == 13:
            self.Destroy()

    def match(self, event, df, frame):
        mat = df.values
        self.clear(mat)     # 清空原先数据

        stu_id = frame.stu_id.GetValue()
        name = frame.name.GetValue()
        course = frame.course.GetValue()
        s = Search(stu_id, name, course)
        # 判断是否都没填
        if not (stu_id or name or course):
            show_msg('至少填入一个条件', '提示')
        # 判断是否3个都填了
        else:
            if stu_id and name and course:
                res_df = s.three_conditions()
            # 判断是否填了其中2个
            elif bool(stu_id) + bool(name) + bool(course) == 2:
                res_df = s.two_conditions()
            # 剩下的情况只填了1个
            else:
                res_df = s.single_condition()
            if res_df is None or len(res_df) == 0:
                show_msg('无符合条件的学生', '提示')
            else:
                self.show_data(res_df)

    def delete(self, event, df, frame):
        stu_id = frame.stu_id.GetValue()
        mat = df.values
        # 判断是否没填
        if not stu_id:
            show_msg('请填入学号', '提示')
        else:
            del_id = df[df['学号'] == stu_id].index.values
            if del_id:
                df.drop(del_id, inplace=True)
                dlg = DelOrNotDialog(self)
                dlg.ShowModal()
                if dlg.flag:
                    df.to_excel('学生信息.xlsx', index=False)
                    show_msg('删除成功', '提示')
            else:
                show_msg('无符合条件的学生', '提示')
            frame.Destroy()
            # 获取原先显示数据的格子，依次清空，作为初始化
            self.clear(mat)
                    
    def clear(self, mat):
        r, c = mat.shape
        for i in range(r):
            for j in range(c):
                self.grid.SetCellValue(i, j, '')

    def show_data(self, df):
        row = len(df.index)
        if row > 25:
            self.grid.AppendRows(row - 25)
        for i in range(row):
            for k, info in enumerate(list(df.iloc[i])):
                print(k, info)
                self.grid.SetCellValue(i, k, info)


# Excel数据交互
class ExcelData:
    def __init__(self):
        if not os.path.exists('学生信息.xlsx'):
            # MySql处理则直接定义各字段数据类型即可
            pd.DataFrame({'学号': '', '姓名': '', '性别': '', '学院': '', '专业': '', '课程': ''}).to_excel('学生信息.xlsx')
        self.df = pd.read_excel('学生信息.xlsx')
        self.df['学号'] = pd.DataFrame(list(map(self._turn_type, self.df['学号'])))

    def _turn_type(self, stu_id):  # 将学号类型转字符
        return str(stu_id)

    def delete(self, data):  # 删
        if isinstance(data, dict):
            pass
        else:
            pass
        self.df.to_excel('学生信息.xlsx', index=False)


# 查询逻辑
class Search:
    def __init__(self, stu_id, name, course):
        self.df = ExcelData().df
        self.stu_id = stu_id
        self.name = name
        self.course = course

    def three_conditions(self):
        try:
            df = self.df[(self.df['学号'] == str(self.stu_id)) & (self.df['姓名'] == self.name) &
                         (self.df['课程'] == str(self.course))]
        except KeyError:
            df = None
        return df

    def two_conditions(self):
        try:
            if bool(self.stu_id) == 0:
                df = self.df[(self.df['姓名'] == str(self.name)) & (self.df['课程'] == self.course)]
            elif bool(self.name) == 0:
                df = self.df[(self.df['学号'] == str(self.stu_id)) & (self.df['课程'] == self.course)]
            else:
                df = self.df[(self.df['学号'] == str(self.stu_id)) & (self.df['姓名'] == self.name)]
        except KeyError:
            df = None
        return df

    def single_condition(self):
        try:
            if self.stu_id:
                df = self.df[self.df['学号'] == str(self.stu_id)]
            elif self.name:
                df = self.df[self.df['姓名'] == str(self.name)]
            else:
                df = self.df[self.df['课程'] == str(self.course)]
        except KeyError:
            df = None
        return df


# 查询界面
class SearchFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, 1, '查询', style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)
        self.SetBackgroundColour('white')

        sizer = wx.BoxSizer(wx.VERTICAL)
        texts = ['按学号查找', '按姓名查找', '按课程查找']
        self._addbox(sizer, texts)

        btnsizer = wx.StdDialogButtonSizer()  # 确认取消按钮

        if wx.Platform != "__WXMSW__":
            btn = wx.ContextHelpButton(self)
            btnsizer.AddButton(btn)

        self.btn1 = wx.Button(self, wx.ID_OK)
        self.btn1.SetDefault()
        btnsizer.AddButton(self.btn1)

        self.btn2 = wx.Button(self, wx.ID_CANCEL)
        btnsizer.AddButton(self.btn2)
        self.Bind(wx.EVT_BUTTON, self._cancel, self.btn2)
        btnsizer.Realize()

        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)

    def _addbox(self, sizer, texts):
        for text in texts:
            box = wx.BoxSizer(wx.HORIZONTAL)
            label = wx.StaticText(self, -1, text)
            box.Add(label, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
            if '学号' in text:
                self.stu_id = wx.TextCtrl(self, -1, '', size=(80, -1))
                box.Add(self.stu_id, 1, wx.ALIGN_CENTRE | wx.ALL, 5)
            elif '姓名' in text:
                self.name = wx.TextCtrl(self, -1, '', size=(80, -1))
                box.Add(self.name, 1, wx.ALIGN_CENTRE | wx.ALL, 5)
            elif '课程' in text:
                self.course = wx.TextCtrl(self, -1, '', size=(80, -1))
                box.Add(self.course, 1, wx.ALIGN_CENTRE | wx.ALL, 5)
            sizer.Add(box, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)

    def _cancel(self, event):
        self.Destroy()


# 增加界面
class AddFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, -1, '新增', size=(720, 300))
        panel = wx.Panel(self, -1)
        self.grid = wx.grid.Grid(panel, -1)
        self.collabels = ['学号', '姓名', '性别', '年级', '学院', '专业', '课程']
        colwidths = [120, 80, 40, 60, 100, 100, 100]
        # 按钮显示文字
        self.loadButton = wx.Button(panel, label="保存数据")
        # 显示批量输入框
        self.hbox = wx.BoxSizer()
        self.hbox.Add(self.loadButton, proportion=0, flag=wx.LEFT, border=5)
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
        self.input_matrix = []

        self.creategrid(colwidths)
        panel.SetSizer(self.vbox)

        self.loadButton.Bind(wx.EVT_BUTTON, self.Save, self.loadButton)

    def creategrid(self, colwidths):
        self.grid.CreateGrid(5, len(self.collabels))
        k = 0
        for i, j in zip(self.collabels, colwidths):
            self.grid.SetColLabelValue(k, i)
            self.grid.SetColSize(k, j)
            k += 1
        self.vbox.Add(self.grid, proportion=0, flag=wx.EXPAND | wx.ALL, border=1)

    def Save(self, event):
        cols = len(self.collabels)
        ls = []
        df = ExcelData().df
        print(df['学号'])
        for row in range(5):
            stu_id = self.grid.GetCellValue(row, 0)
            print(stu_id)
            if stu_id == '':
                continue
            if stu_id in df['学号'].values:   # 学号唯一性，其他都不唯一
                show_msg(f'学号{stu_id}已存在，请确认学生信息', '错误')
                continue
            each_info = []
            for col in range(cols):
                each_info.append(self.grid.GetCellValue(row, col))
            ls.append(dict(zip(self.collabels, each_info)))
        if ls:  # 信息非空才保存
            df_new = pd.DataFrame(ls)
            df_new = df_new[['学号', '姓名', '性别', '年级', '学院', '专业', '课程']]
            # 读取已有数据，拼接后保存
            pd.concat([df, df_new]).to_excel('学生信息.xlsx', index=False)
            show_msg("已保存", "提示")


# 删除界面
class DeleteFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, 1, '删除', style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)
        self.SetBackgroundColour('white')

        sizer = wx.BoxSizer(wx.VERTICAL)
        box = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(self, -1, '输入学号删除')
        box.Add(label, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
        self.stu_id = wx.TextCtrl(self, -1, '', size=(80, -1))
        box.Add(self.stu_id, 1, wx.ALIGN_CENTRE | wx.ALL, 5)
        sizer.Add(box, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)

        btnsizer = wx.StdDialogButtonSizer()  # 确认取消按钮

        if wx.Platform != "__WXMSW__":
            btn = wx.ContextHelpButton(self)
            btnsizer.AddButton(btn)

        self.btn1 = wx.Button(self, wx.ID_OK)
        self.btn1.SetDefault()
        btnsizer.AddButton(self.btn1)

        self.btn2 = wx.Button(self, wx.ID_CANCEL)
        btnsizer.AddButton(self.btn2)
        self.Bind(wx.EVT_BUTTON, self._cancel, self.btn2)
        btnsizer.Realize()

        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)

    def _cancel(self, event):
        self.Destroy()


# 确认删除窗口
class DelOrNotDialog(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, title='提示')
        self.SetBackgroundColour('white')
        self.flag = False
        sizer = wx.BoxSizer(wx.VERTICAL)
        label = wx.StaticText(self, -1, '是否确认删除')
        sizer.Add(label, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)

        btnsizer = wx.StdDialogButtonSizer()  # 确认取消按钮

        if wx.Platform != "__WXMSW__":
            btn = wx.ContextHelpButton(self)
            btnsizer.AddButton(btn)

        self.btn1 = wx.Button(self, wx.ID_OK)
        self.btn1.SetDefault()
        self.Bind(wx.EVT_BUTTON, self.sure, self.btn1)
        btnsizer.AddButton(self.btn1)

        self.btn2 = wx.Button(self, wx.ID_CANCEL)
        btnsizer.AddButton(self.btn2)
        self.Bind(wx.EVT_BUTTON, self._cancel, self.btn2)
        btnsizer.Realize()

        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)

    def sure(self, event):
        self.flag = True
        self.Destroy()

    def _cancel(self, event):
        self.Destroy()


# 消息弹框
def show_msg(msg, title):
    wx.MessageBox(msg, title, wx.OK | wx.ICON_INFORMATION)
